package com.yjzx.util.service.http;


import com.alibaba.fastjson.JSONObject;
import com.yjzx.util.service.http.bean.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpStatus;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

/**
 * @author yjzx
 * @date 2024/01/03
 * @description 多线程连接池管理
 */
@Slf4j
public class HttpManager {

    /**
     * 线程池管理
     */
    private static PoolingHttpClientConnectionManager poolConnManager = null;

    static {
        try {
            SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(builder.build());
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .register("https", sslConnectionSocketFactory)
                    .build();
            // 初始化连接管理器
            poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            poolConnManager.setMaxTotal(64);
            // 设置最大路由
            poolConnManager.setDefaultMaxPerRoute(32);
        } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
            e.printStackTrace();
            throw new RuntimeException("httpclient连接池初始化失败！！");
        }
    }

    private static CloseableHttpClient getConnection() {
        RequestConfig config = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
        return HttpClients.custom()
                // 设置连接池管理
                .setConnectionManager(poolConnManager)
                .setDefaultRequestConfig(config)
                // 设置重试次数
                .setRetryHandler(new DefaultHttpRequestRetryHandler(2, false)).build();
    }
    static String get(String url,Header... heads){
        try {
            HttpGet httpGet = new HttpGet(url);

            if (heads != null && heads.length > 0) {
                httpGet.setHeaders(heads);
            }
            try (CloseableHttpResponse response = getConnection().execute(httpGet)) {
                int code = response.getStatusLine().getStatusCode();
                String result = EntityUtils.toString(response.getEntity());
                if (code == HttpStatus.OK.value()) {
                    return result;
                }
                log.error("=====>>发起请求:{},返回错误码:{},返回结果:{}", url, code, result);
                throw new RuntimeException("=====>>发起请求出现异常！");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    static String post(String url, Body body, Header... heads) {
        try {
            String bodyStr = JSONObject.toJSONString(body);
            HttpPost httpPost = new HttpPost(url);
            if (log.isDebugEnabled()) {
                log.debug("=====>>向[{}]发起请求数据：{}", url, bodyStr);
            }
            StringEntity paramEntity = new StringEntity(bodyStr);
            paramEntity.setContentEncoding("UTF-8");
            paramEntity.setContentType("application/json");
            httpPost.setEntity(paramEntity);
            if (heads != null && heads.length > 0) {
                httpPost.setHeaders(heads);
            }
            try (CloseableHttpResponse response = getConnection().execute(httpPost)) {
                int code = response.getStatusLine().getStatusCode();
                String result = EntityUtils.toString(response.getEntity());
                if (code == HttpStatus.OK.value()) {
                    return result;
                }
                log.error("=====>>发起请求:{},返回错误码:{},请求参数:{},返回结果:{}", url, code, body, result);
                throw new RuntimeException("=====>>发起请求出现异常！");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static boolean exec(BaseParam param) {
        AuthKey authKey = param.getAuthKey();
        String str;
        boolean flag = false;
        String url = authKey.getServerHost() + param.uri();
        Body makeBody = param.makeBody();
        log.info("=====>>向{}发起明文请求数据：{}",param.uri(),  JSONObject.toJSONString(param));
        str = post(url, makeBody);
        if (log.isDebugEnabled()) {
            log.debug("=====>>获得响应数据：{}",  str);
        }
        Result res = JSONObject.parseObject(str, Result.class);
        if (res != null) {
            RetEnum retEnum = RetEnum.getRetEnum(res.getRet());
            if (RetEnum.ok.equals(retEnum)) {
                log.info("=====>>获得响应数据：{}",  str);
                flag = true;
            } else {
                log.error("=====>>{}，异常响应数据：{}", retEnum.getMessage(), str);
            }
        }
        return flag;
    }

}